home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / dsp / 56ktools / dspkgctr.z / dspkgctr / gcc / genemit.c < prev    next >
C/C++ Source or Header  |  1992-06-08  |  12KB  |  493 lines

  1. /* Generate code from machine description to emit insns as rtl.
  2.    Copyright (C) 1987, 1988 Free Software Foundation, Inc.
  3.  
  4.    $Id: genemit.c,v 1.2 91/08/06 10:01:23 jeff Exp $
  5.  
  6. This file is part of GNU CC.
  7.  
  8. GNU CC is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 1, or (at your option)
  11. any later version.
  12.  
  13. GNU CC is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with GNU CC; see the file COPYING.  If not, write to
  20. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  21.  
  22.  
  23. #include <stdio.h>
  24. #include "config.h"
  25. #include "rtl.h"
  26. #include "obstack.h"
  27.  
  28. struct obstack obstack;
  29. struct obstack *rtl_obstack = &obstack;
  30.  
  31. #define obstack_chunk_alloc xmalloc
  32. #define obstack_chunk_free free
  33. extern int xmalloc ();
  34. extern void free ();
  35.  
  36. void fatal ();
  37. void fancy_abort ();
  38.  
  39. int max_opno;
  40. int max_dup_opno;
  41. int register_constraints;
  42. int insn_code_number;
  43.  
  44. #define max(a, b) ((a) > (b) ? (a) : (b))
  45.  
  46. void
  47. max_operand_1 (x)
  48.      rtx x;
  49. {
  50.   register RTX_CODE code;
  51.   register int i;
  52.   register int len;
  53.   register char *fmt;
  54.  
  55.   if (x == 0)
  56.     return;
  57.  
  58.   code = GET_CODE (x);
  59.  
  60.   if (code == MATCH_OPERAND && XSTR (x, 2) != 0)
  61.     register_constraints = 1;
  62.   if (code == MATCH_OPERAND || code == MATCH_OPERATOR)
  63.     max_opno = max (max_opno, XINT (x, 0));
  64.   if (code == MATCH_DUP)
  65.     max_dup_opno = max (max_dup_opno, XINT (x, 0));
  66.  
  67.   fmt = GET_RTX_FORMAT (code);
  68.   len = GET_RTX_LENGTH (code);
  69.   for (i = 0; i < len; i++)
  70.     {
  71.       if (fmt[i] == 'e' || fmt[i] == 'u')
  72.     max_operand_1 (XEXP (x, i));
  73.       else if (fmt[i] == 'E')
  74.     {
  75.       int j;
  76.       for (j = 0; j < XVECLEN (x, i); j++)
  77.         max_operand_1 (XVECEXP (x, i, j));
  78.     }
  79.     }
  80. }
  81.  
  82. int
  83. max_operand_vec (insn, arg)
  84.      rtx insn;
  85.      int arg;
  86. {
  87.   register int len = XVECLEN (insn, arg);
  88.   register int i;
  89.  
  90.   max_opno = -1;
  91.   max_dup_opno = -1;
  92.  
  93.   for (i = 0; i < len; i++)
  94.     max_operand_1 (XVECEXP (insn, arg, i));
  95.  
  96.   return max_opno + 1;
  97. }
  98.  
  99. void
  100. print_code (code)
  101.      RTX_CODE code;
  102. {
  103.   register char *p1;
  104.   for (p1 = GET_RTX_NAME (code); *p1; p1++)
  105.     {
  106.       if (*p1 >= 'a' && *p1 <= 'z')
  107.     putchar (*p1 + 'A' - 'a');
  108.       else
  109.     putchar (*p1);
  110.     }
  111. }
  112.  
  113. /* Print a C expression to construct an RTX just like X,
  114.    substituting any operand references appearing within.  */
  115.  
  116. void
  117. gen_exp (x)
  118.      rtx x;
  119. {
  120.   register RTX_CODE code;
  121.   register int i;
  122.   register int len;
  123.   register char *fmt;
  124.  
  125.   if (x == 0)
  126.     {
  127.       printf ("0");
  128.       return;
  129.     }
  130.  
  131.   code = GET_CODE (x);
  132.  
  133.   switch (code)
  134.     {
  135.     case MATCH_OPERAND:
  136.     case MATCH_DUP:
  137.       printf ("operand%d", XINT (x, 0));
  138.       return;
  139.  
  140.     case MATCH_OPERATOR:
  141.       printf ("gen_rtx (GET_CODE (operand%d)", XINT (x, 0));
  142.       printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
  143.       for (i = 0; i < XVECLEN (x, 2); i++)
  144.     {
  145.       printf (",\n\t\t");
  146.       gen_exp (XVECEXP (x, 2, i));
  147.     }
  148.       printf (")");
  149.       return;
  150.  
  151.     case ADDRESS:
  152.       fatal ("ADDRESS expression code used in named instruction pattern");
  153.  
  154.     case PC:
  155.       printf ("pc_rtx");
  156.       return;
  157.  
  158.     case CC0:
  159.       printf ("cc0_rtx");
  160.       return;
  161.  
  162.     case CONST_INT:
  163.       if (INTVAL (x) == 0)
  164.     {
  165.       printf ("const0_rtx");
  166.       return;
  167.     }
  168.       if (INTVAL (x) == 1)
  169.     {
  170.       printf ("const1_rtx");
  171.       return;
  172.     }
  173.     }
  174.  
  175.   printf ("gen_rtx (");
  176.   print_code (code);
  177.   printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
  178.  
  179.   fmt = GET_RTX_FORMAT (code);
  180.   len = GET_RTX_LENGTH (code);
  181.   for (i = 0; i < len; i++)
  182.     {
  183.       if (fmt[i] == '0')
  184.     break;
  185.       printf (", ");
  186.       if (fmt[i] == 'e' || fmt[i] == 'u')
  187.     gen_exp (XEXP (x, i));
  188.       else if (fmt[i] == 'i')
  189.     printf ("%d", XINT (x, i));
  190.       else if (fmt[i] == 's')
  191.     printf ("\"%s\"", XSTR (x, i));
  192.       else if (fmt[i] == 'E')
  193.     {
  194.       int j;
  195.       printf ("gen_rtvec (%d", XVECLEN (x, i));
  196.       for (j = 0; j < XVECLEN (x, i); j++)
  197.         {
  198.           printf (",\n\t\t");
  199.           gen_exp (XVECEXP (x, i, j));
  200.         }
  201.       printf (")");
  202.     }
  203.       else
  204.     abort ();
  205.     }
  206.   printf (")");
  207. }  
  208.  
  209. /* Generate the `gen_...' function for a DEFINE_INSN.  */
  210.  
  211. void
  212. gen_insn (insn)
  213.      rtx insn;
  214. {
  215.   int operands;
  216.   register int i;
  217.  
  218.   /* Don't mention instructions whose names are the null string.
  219.      They are in the machine description just to be recognized.  */
  220.   if (strlen (XSTR (insn, 0)) == 0)
  221.     return;
  222.  
  223.   /* Find out how many operands this function has,
  224.      and also whether any of them have register constraints.  */
  225.   register_constraints = 0;
  226.   operands = max_operand_vec (insn, 1);
  227.   if (max_dup_opno >= operands)
  228.     fatal ("match_dup operand number has no match_operand");
  229.  
  230.   /* Output the function name and argument declarations.  */
  231.   printf ("rtx\ngen_%s (", XSTR (insn, 0));
  232.   for (i = 0; i < operands; i++)
  233.     printf (i ? ", operand%d" : "operand%d", i);
  234.   printf (")\n");
  235.   for (i = 0; i < operands; i++)
  236.     printf ("     rtx operand%d;\n", i);
  237.   printf ("{\n");
  238.  
  239.   /* Output code to construct and return the rtl for the instruction body */
  240.  
  241.   if (XVECLEN (insn, 1) == 1)
  242.     {
  243.       printf ("  return ");
  244.       gen_exp (XVECEXP (insn, 1, 0));
  245.       printf (";\n}\n\n");
  246.     }
  247.   else
  248.     {
  249.       printf ("  return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (%d", XVECLEN (insn, 1));
  250.       for (i = 0; i < XVECLEN (insn, 1); i++)
  251.     {
  252.       printf (",\n\t\t");
  253.       gen_exp (XVECEXP (insn, 1, i));
  254.     }
  255.       printf ("));\n}\n\n");
  256.     }
  257. }
  258.  
  259. /* Generate the `gen_...' function for a DEFINE_EXPAND.  */
  260.  
  261. void
  262. gen_expand (expand)
  263.      rtx expand;
  264. {
  265.   int operands;
  266.   register int i;
  267.  
  268.   if (strlen (XSTR (expand, 0)) == 0)
  269.     fatal ("define_expand lacks a name");
  270.   if (XVEC (expand, 1) == 0)
  271.     fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
  272.  
  273.   /* Find out how many operands this function has,
  274.      and also whether any of them have register constraints.  */
  275.   register_constraints = 0;
  276.  
  277.   operands = max_operand_vec (expand, 1);
  278.  
  279.   /* Output the function name and argument declarations.  */
  280.   printf ("rtx\ngen_%s (", XSTR (expand, 0));
  281.   for (i = 0; i < operands; i++)
  282.     printf (i ? ", operand%d" : "operand%d", i);
  283.   printf (")\n");
  284.   for (i = 0; i < operands; i++)
  285.     printf ("     rtx operand%d;\n", i);
  286.   printf ("{\n");
  287.  
  288.   /* For each operand referred to only with MATCH_DUPs,
  289.      make a local variable.  */
  290.   for (i = operands; i <= max_dup_opno; i++)
  291.     printf ("  rtx operand%d;\n", i);
  292.   printf ("  rtx operands[%d];\n", max (operands, max_dup_opno + 1));
  293.   printf ("  rtx _val;\n");
  294.   printf ("  start_sequence ();\n");
  295.  
  296.   /* The fourth operand of DEFINE_EXPAND is some code to be executed
  297.      before the actual construction.
  298.      This code expects to refer to `operands'
  299.      just as the output-code in a DEFINE_INSN does,
  300.      but here `operands' is an automatic array.
  301.      So copy the operand values there before executing it.  */
  302.   if (XSTR (expand, 3))
  303.     {
  304.       /* Output code to copy the arguments into `operands'.  */
  305.       for (i = 0; i < operands; i++)
  306.     printf ("  operands[%d] = operand%d;\n", i, i);
  307.  
  308.       /* Output the special code to be executed before the sequence
  309.      is generated.  */
  310.       printf ("%s\n", XSTR (expand, 3));
  311.  
  312.       /* Output code to copy the arguments back out of `operands'
  313.      (unless we aren't going to use them at all).  */
  314.       if (XVEC (expand, 1) != 0)
  315.     {
  316.       for (i = 0; i < operands; i++)
  317.         printf ("  operand%d = operands[%d];\n", i, i);
  318.       for (; i <= max_dup_opno; i++)
  319.         printf ("  operand%d = operands[%d];\n", i, i);
  320.     }
  321.     }
  322.  
  323.   /* Output code to construct the rtl for the instruction bodies.
  324.      Use emit_insn to add them to the sequence being accumulated.
  325.      But don't do this if the user's code has set `no_more' nonzero.  */
  326.  
  327.   for (i = 0; i < XVECLEN (expand, 1); i++)
  328.     {
  329.       rtx next = XVECEXP (expand, 1, i);
  330.       if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
  331.       || (GET_CODE (next) == PARALLEL
  332.           && GET_CODE (XVECEXP (next, 0, 0)) == SET
  333.           && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
  334.       || GET_CODE (next) == RETURN)
  335.     printf ("  emit_jump_insn (");
  336.       else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
  337.            || GET_CODE (next) == CALL
  338.            || (GET_CODE (next) == PARALLEL
  339.            && GET_CODE (XVECEXP (next, 0, 0)) == SET
  340.            && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
  341.            || (GET_CODE (next) == PARALLEL
  342.            && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
  343.     printf ("  emit_call_insn (");
  344.       else if (GET_CODE (next) == CODE_LABEL)
  345.     printf ("  emit_label (");
  346.       else if (GET_CODE (next) == MATCH_OPERAND
  347.            || GET_CODE (next) == MATCH_OPERATOR
  348.            || GET_CODE (next) == MATCH_DUP
  349.            || GET_CODE (next) == PARALLEL)
  350.     printf ("  emit (");
  351.       else
  352.     printf ("  emit_insn (");
  353.       gen_exp (next);
  354.       printf (");\n");
  355.       if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
  356.       && GET_CODE (SET_SRC (next)) == LABEL_REF)
  357.     printf ("  emit_barrier ();");
  358.     }
  359.  
  360.   /* Call `gen_sequence' to make a SEQUENCE out of all the
  361.      insns emitted within this gen_... function.  */
  362.  
  363.   printf (" _done:\n");
  364.   printf ("  _val = gen_sequence ();\n");
  365.   printf ("  end_sequence ();\n");
  366.   printf ("  return _val;\n}\n\n");
  367. }
  368.  
  369. int
  370. xmalloc (size)
  371. {
  372.   register int val = malloc (size);
  373.  
  374.   if (val == 0)
  375.     fatal ("virtual memory exhausted");
  376.  
  377.   return val;
  378. }
  379.  
  380. int
  381. xrealloc (ptr, size)
  382.      char *ptr;
  383.      int size;
  384. {
  385.   int result = realloc (ptr, size);
  386.   if (!result)
  387.     fatal ("virtual memory exhausted");
  388.   return result;
  389. }
  390.  
  391. void
  392. fatal (s, a1, a2)
  393.      char *s;
  394. {
  395.   fprintf (stderr, "genemit: ");
  396.   fprintf (stderr, s, a1, a2);
  397.   fprintf (stderr, "\n");
  398.   exit (FATAL_EXIT_CODE);
  399. }
  400.  
  401. /* More 'friendly' abort that prints the line and file.
  402.    config.h can #define abort fancy_abort if you like that sort of thing.  */
  403.  
  404. void
  405. fancy_abort ()
  406. {
  407.   fatal ("Internal gcc abort.");
  408. }
  409.  
  410. int
  411. main (argc, argv)
  412.      int argc;
  413.      char **argv;
  414. {
  415.   rtx desc;
  416.   FILE *infile;
  417.   extern rtx read_rtx ();
  418.   register int c;
  419.  
  420.   obstack_init (rtl_obstack);
  421.  
  422.   if (argc <= 1)
  423.     fatal ("No input file name.");
  424.  
  425.   infile = fopen (argv[1], "r");
  426.   if (infile == 0)
  427.     {
  428.       perror (argv[1]);
  429.       exit (FATAL_EXIT_CODE);
  430.     }
  431.  
  432.   init_rtl ();
  433.  
  434.   /* Assign sequential codes to all entries in the machine description
  435.      in parallel with the tables in insn-output.c.  */
  436.  
  437.   insn_code_number = 0;
  438.  
  439.   printf ("/* Generated automatically by the program `genemit'\n\
  440. from the machine description file `md'.  */\n\n");
  441.  
  442.   printf ("#include \"config.h\"\n");
  443.   printf ("#include \"rtl.h\"\n");
  444.   printf ("#include \"expr.h\"\n");
  445.   printf ("#include \"real.h\"\n");
  446. #if defined( DSP56000 ) || defined( DSP96000 )
  447.   printf ("#if defined( _INTELC32_ )\n" );
  448.   printf ("#include \"iconfig.h\"\n");
  449.   printf ("#include \"iflags.h\"\n\n");
  450.   printf ("#else\n" );
  451.   printf ("#include \"insn-config.h\"\n");
  452.   printf ("#include \"insn-flags.h\"\n\n");
  453.   printf ("#endif\n" );
  454. #else
  455.   printf ("#include \"insn-config.h\"\n\n");
  456.   printf ("#include \"insn-flags.h\"\n\n");
  457. #endif
  458.   printf ("extern char *insn_operand_constraint[][MAX_RECOG_OPERANDS];\n\n");
  459.   printf ("extern rtx recog_operand[];\n");
  460.   printf ("#define operands emit_operand\n\n");
  461.   printf ("#define FAIL do { end_sequence (); return 0;} while (0)\n\n");
  462.   printf ("#define DONE goto _done\n\n");
  463.  
  464.   /* Read the machine description.  */
  465.  
  466.   while (1)
  467.     {
  468.       c = read_skip_spaces (infile);
  469.       if (c == EOF)
  470.     break;
  471.       ungetc (c, infile);
  472.  
  473.       desc = read_rtx (infile);
  474.       if (GET_CODE (desc) == DEFINE_INSN)
  475.     {
  476.       gen_insn (desc);
  477.       ++insn_code_number;
  478.     }
  479.       if (GET_CODE (desc) == DEFINE_EXPAND)
  480.     {
  481.       gen_expand (desc);
  482.       ++insn_code_number;
  483.     }
  484.       if (GET_CODE (desc) == DEFINE_PEEPHOLE)
  485.     {
  486.       ++insn_code_number;
  487.     }
  488.     }
  489.  
  490.   fflush (stdout);
  491.   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
  492. }
  493.